package smallChanges.lineNumberMapping;

import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

/**
 * A collection of ReissResults.  For example, the ReissResults
 * for three different runs of LDiff all put together.
 * 
 * The goal of this class is to generate a single XML output
 * file for several different configurations.
 * 
 * @author jspacco
 *
 */
public class ReissResultsCollection
{
    private int numVersions;
    private ReissConfig config;
    private Map<String,ReissResults> resultsMap=new HashMap<String,ReissResults>();
    private Map<String, Map<Integer,Long>> timingMap=new HashMap<String,Map<Integer,Long>>();
        private Map<Integer,ReissLocationMap> locationMap=
        new TreeMap<Integer,ReissLocationMap>();
    
    public ReissResultsCollection(ReissConfig config) {
        this.config=config;
        this.numVersions=config.getNumVersions();
    }
    
    public void addTimingInfo(String method, int version, long time) {
        if (!timingMap.containsKey(method)) {
            timingMap.put(method, new HashMap<Integer,Long>());
        }
        if (!timingMap.get(method).containsKey(version)) {
            timingMap.get(method).put(version, 0L);
        }
        long total=timingMap.get(method).get(version);
        timingMap.get(method).put(version, total+time);
    }
    
    public long getAverageTimeForMethod(String method) {
        long total=0L;
        int count=0;
        for (Map.Entry<Integer,Long> entry : timingMap.get(method).entrySet()) {
            total += entry.getValue();
            count++;
        }
        return total/count;
    }

    
    public ReissScore getOverallScore(String method) {
        return resultsMap.get(method).getOverallScore();
    }
    
    public ReissLocationMap getReissLocationMap(int versionNum) {
        if (!locationMap.containsKey(versionNum)) {
            locationMap.put(versionNum, new ReissLocationMap());
        }
        return locationMap.get(versionNum);
    }
    
    public String toXMLString() {
        StringBuffer buf=new StringBuffer();

        buf.append("<LIMBOTEST>\n");
        for (int version=2; version <= numVersions; version++) {
            ReissLocationMap rlm=locationMap.get(version);
            buf.append("<VERSION NUMBER=\"" +version+"\">\n");
            for (Map.Entry<String,ReissResults> entry : resultsMap.entrySet()) {
                buf.append(rlm.toXMLString()+"\n");
            }
            buf.append("</VERSION>\n");
        }
        buf.append("<SCORES>\n");
        for (Map.Entry<String,ReissResults> entry : resultsMap.entrySet()) {
            String method=entry.getKey();
            ReissResults results=entry.getValue();
            buf.append(results.getOverallScore().toXMLString(method, getAverageTimeForMethod(method))+"\n");
        }
        buf.append("</SCORES>\n");
        buf.append("</LIMBOTEST>\n");
        return buf.toString();
    }

    public void add(ReissResults results)
    {
        String method=results.getMethod();
        resultsMap.put(method, results);
    }

    public void putScore(String method, int versionNum, ReissScore score)
    {
        if (!resultsMap.containsKey(method)) {
            resultsMap.put(method, new ReissResults(method));
        }
        resultsMap.get(method).putScore(versionNum, score);
    }
}
